//
// Created by 张祎鹤严 on 2022/12/12.
//

#include "bsp_ina226.h"

INA226 INA226_data;
uint8_t t1,t2,t3,t4,t5,t6,t7;

void INA226_Init(void)
{
    IIC_SCL_H;
    IIC_SDA_H;
    HAL_Delay(10);

    INA226_SendData(INA226_ADDR1,CFG_REG,0x8000);	//重新启动
    INA226_SendData(INA226_ADDR1,CFG_REG,0x484f);	//设置转换时间204us,求平均值次数128，采样时间为204*128，设置模式为分流和总线连续模式
    //INA226_SendData(INA226_ADDR1,CAL_REG,CAL);	//设置分辨率
    INA226_SendData(INA226_ADDR1,CAL_REG,0x0A00);
    INA226_Get_ID(INA226_ADDR1);					//获取ina226的id
    //INA226_SendData(INA226_ADDR1,CFG_REG,0x4727);

}
void INA226_SetRegPointer(uint8_t addr,uint8_t reg)
{
    IIC_Start();

    IIC_Send_Byte(addr);
    t1 = IIC_Wait_Ack();

    IIC_Send_Byte(reg);
    t2 = IIC_Wait_Ack();

    IIC_Stop();
}

//发送,写入
void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data)
{
    uint8_t temp=0;
    IIC_Start();

    IIC_Send_Byte(addr);
    t3 = IIC_Wait_Ack();

    IIC_Send_Byte(reg);
    t4 = IIC_Wait_Ack();

    temp = (uint8_t)(data >> 8);
    IIC_Send_Byte(temp);
    t5 = IIC_Wait_Ack();

    temp = (uint8_t)(data & 0x00FF);
    IIC_Send_Byte(temp);
    t6 = IIC_Wait_Ack();

    IIC_Stop();
}

//读取
uint16_t INA226_ReadData(uint8_t addr)
{
    uint16_t temp = 0;
    IIC_Start();

    IIC_Send_Byte(addr + 1);
    t7 = IIC_Wait_Ack();

    temp = IIC_Read_Byte(1);
    temp <<= 8;
    temp |= IIC_Read_Byte(0);

    IIC_Stop();
    return temp;
}

int32_t INA226_GetShunt_Current(uint8_t addr)
{
    int32_t temp = 0;
    INA226_SetRegPointer(addr,CUR_REG);
    temp = INA226_ReadData(addr);
    if(temp & 0x8000){
        temp = ~(temp - 1);
        //temp = (uint16_t)temp - 2 * (uint16_t)temp;
    }
    return temp;
}

//获取 id
void INA226_Get_ID(uint8_t addr)
{
    uint32_t temp = 0;
    INA226_SetRegPointer(addr,INA226_GET_ADDR);
    temp = INA226_ReadData(addr);
    INA226_data.INA226_id = temp;
}

//获取校准值
uint16_t INA226_GET_CAL_REG(uint8_t addr)
{
    uint32_t temp = 0;
    INA226_SetRegPointer(addr,CAL_REG);
    temp = INA226_ReadData(addr);
    return (uint16_t)temp;
}

//1.25mV/bit
uint32_t INA226_GetVoltage(uint8_t addr)
{
    uint32_t temp = 0;
    INA226_SetRegPointer(addr,BV_REG);
    temp = INA226_ReadData(addr);
    return (uint32_t)temp;
}

uint32_t INA226_GetShuntVoltage(uint8_t addr)
{
    uint32_t temp=0;
    INA226_SetRegPointer(addr,SV_REG);
    temp = INA226_ReadData(addr);
    if(temp & 0x8000)
        temp = ~(temp - 1);
    return (uint32_t)temp;
}

void GetVoltage(float *Voltage)
{
    *Voltage = (float)((float)(INA226_GetVoltage(INA226_ADDR1)) * (float)Voltage_LSB);
}

void Get_Shunt_voltage(float *Voltage)//uV
{
    *Voltage = (float)((float)(INA226_GetShuntVoltage(INA226_ADDR1)) * (float)INA226_VAL_LSB);
}

void Get_Shunt_Current(float *Current)//mA
{
    *Current = (float)((float)(INA226_GetShunt_Current(INA226_ADDR1)) * (float)CURRENT_LSB);
}

void GetPower(void)
{
    vTaskSuspendAll();
    taskENTER_CRITICAL();
    float temp;
    GetVoltage(&INA226_data.voltageVal);
    Get_Shunt_voltage(&INA226_data.Shunt_voltage);	//uV
    Get_Shunt_Current(&INA226_data.Shunt_Current);	//mA
    temp = 24 * INA226_data.Shunt_Current * 0.001f;
    if(temp <= 480)
        INA226_data.Power_Val = temp;
    taskEXIT_CRITICAL();
    xTaskResumeAll();
}


/*
#include "bsp_ina226.h"
#include "i2c.h"
#include "stm32f405xx.h"
#include "main.h"
#include "cmsis_os.h"
#include "driver_chassis.h"
//	接线说明：
//	硬件IIC:
// PA8   ------> I2C3_SCL
// PC9   ------> I2C3_SDA

INA226 ina226_data;
uint8_t Transmit_ModeFLag;
uint8_t Read_SR1_Flag = 0;     //传输状态标志1，0为读阶段1，1为读阶段2，要记得清零
uint8_t Read_buf[2] = { 0 };
uint8_t Write_buf[4] = { 0 };
uint8_t regAdder[3] = { CUR_REG, SV_REG, BV_REG };
uint8_t n = 2, i = 0, j = 2;         //n与regAdder[]的长度减1一样
int16_t temp[3];            //与regAdder[]的长度一样

//芯片初始化
void mx_ina226_init(void)
{
	LL_I2C_EnableIT_EVT(I2C_USE);   //开启I2C事件中断
	LL_I2C_EnableIT_BUF(I2C_USE);
	INA226_SendData(INA226_ADDR1, CFG_REG, 0x8000);    //重新启动
	INA226_SendData(INA226_ADDR1, CFG_REG, 0x484f);    //设置转换时间1.1ms,求平均值次数1024，单个采样时间为1.1*4，设置模式为分流和总线连续模式，总时间1.1*4*2
	INA226_SendData(INA226_ADDR1, CAL_REG, 0x0A00);       //设置分辨率
}

//发送,写入数据
void INA226_SendData(uint8_t _devAdder, uint8_t _regAdder, uint16_t _num)
{

	while (LL_I2C_IsActiveFlag_BUSY(I2C_USE))
		osDelay(1);

	taskENTER_CRITICAL();
	j = 2;
	Transmit_ModeFLag = WRITE_MISSION;
	Write_buf[0] = _devAdder;
	Write_buf[1] = _regAdder;
	Write_buf[2] = (uint8_t)(_num >> 8);
	Write_buf[3] = (uint8_t)(_num & 0x00FF);
	LL_I2C_GenerateStartCondition(I2C_USE);//发送起始位后，自动转换为主设备
	taskEXIT_CRITICAL();
	osDelay(5);

}

//读取数据
void INA226_ReadData(uint8_t _devAdder)
{
	if (!LL_I2C_IsActiveFlag_BUSY(I2C_USE))
	{
		Write_buf[0] = _devAdder;
		Write_buf[1] = regAdder[i];
		Read_SR1_Flag = 0;   //表示读任务的第一阶段，设置寄存器指针
		Transmit_ModeFLag = READ_MISSION;
		LL_I2C_AcknowledgeNextData(I2C_USE, LL_I2C_ACK);    //开启自动应答
		LL_I2C_GenerateStartCondition(I2C_USE);//发送起始位后，自动转换为主设备
	}
}

//i2c事件中断处理函数
uint16_t flag = 0;
uint16_t check = 0;

void I2C_IT_EVENT_SELECT(void)   //用于发送地址和判断当前事件状态
{
	flag = I2C_USE->SR1;
	if (flag & 0x0001)
	{        //--生成起始位(SB未清零-LL_I2C_IsActiveFlag_SB读了SR1,在后续发送地址时 LL_I2C_TransmitData8写了DR后清除SB位)
		check = 1;
		switch (Transmit_ModeFLag)
		{
		case (READ_MISSION):
			if (Read_SR1_Flag == 1)
			{
				LL_I2C_TransmitData8(I2C_USE, Write_buf[0] + 1);
			}
			else if (Read_SR1_Flag == 0)
			{
				LL_I2C_TransmitData8(I2C_USE, Write_buf[0]);
			}
			break;
		case (WRITE_MISSION):
			LL_I2C_TransmitData8(I2C_USE, Write_buf[0]);
			break;
		}
	}
	else if (flag & 0x0002)
	{
		check = 2;
		switch (Transmit_ModeFLag)
		{
		case (READ_MISSION):
			if (Read_SR1_Flag == 1)
			{
				LL_I2C_AcknowledgeNextData(I2C_USE, LL_I2C_NACK);    //关闭自动应答
				LL_I2C_EnableBitPOS(I2C_USE);//POS位置位
				(void)(I2C_USE->SR1);       //清零事件EV6 ADDR位(先读SR1再读SR2)
				(void)(I2C_USE->SR2);     //清除EV6事件
			}
			else if (Read_SR1_Flag == 0)
			{
				(void)(I2C_USE->SR1);       //清零事件EV6 ADDR位(先读SR1再读SR2)
				(void)(I2C_USE->SR2);     //清除EV6事件
				LL_I2C_TransmitData8(I2C_USE, Write_buf[1]);
			}
			break;
		case (WRITE_MISSION):
			(void)(I2C_USE->SR1);       //清零事件EV6 ADDR位(先读SR1再读SR2)
			(void)(I2C_USE->SR2);     //清除EV6事件
			LL_I2C_TransmitData8(I2C_USE, Write_buf[1]);
			break;    //--发送要写入的目标寄存器
		}
	}
	else if (flag & 0x0040)
	{
		check = 3;
		if (flag & 0x0004)
		{
			LL_I2C_GenerateStopCondition(I2C_USE);
			Read_buf[0] = (uint8_t)LL_I2C_ReceiveData8(I2C_USE);//保存第一个字节
			Read_SR1_Flag = 0;//给移位寄存器转到DR中时间，相当于nop
			Read_buf[1] = (uint8_t)LL_I2C_ReceiveData8(I2C_USE);//保存第二个字节
			temp[i++] = (int16_t)Read_buf[0] << 8 | Read_buf[1];
			if (i > n) i = 0;
			LL_I2C_ClearFlag_STOP(I2C_USE);
		}
	}
	else if (flag & 0x0080)
	{
		check = 4;
		switch (Transmit_ModeFLag)
		{
		case (READ_MISSION):
			if (Read_SR1_Flag == 0)
			{
				LL_I2C_GenerateStartCondition(I2C_USE);
				Read_SR1_Flag = 1;
			}
			break;
		case (WRITE_MISSION):
			if (j != 4) LL_I2C_TransmitData8(I2C_USE, Write_buf[j++]);
			else if (flag & 0x0004) LL_I2C_GenerateStopCondition(I2C_USE);
			break;
		}
	}
	else if (flag & 0x0010) LL_I2C_ClearFlag_STOP(I2C_USE);

}


//获取电压
void GetVoltage(float* Voltage)//mV
{
	*Voltage = (uint16_t)temp[2] * Voltage_LSB;
}

//获取分流电压
void Get_Shunt_voltage(float* Voltage)//uV
{
	if (temp[2] & 0x8000) temp[1] = ~(temp[1] - 1);//取绝对值操作
	*Voltage = ((uint16_t)temp[1] * INA226_VAL_LSB);//如需矫正电流分流参数请将这里改为2.5
}

//获取电流
void Get_Shunt_Current(float* Current)//mA
{
	if (temp[0] & 0x8000) temp[0] = ~(temp[0] - 1);
	*Current = ((uint16_t)temp[0] * CURRENT_LSB);
}

//获取功率= 总线电压 * 电流
void get_power()//W
{
	GetVoltage(&ina226_data.voltageVal);            //mV
	Get_Shunt_voltage(&ina226_data.Shunt_voltage);    //uV
	Get_Shunt_Current(&ina226_data.Shunt_Current);    //mA
	ina226_data.Power_Val = ina226_data.voltageVal * 0.001f * ina226_data.Shunt_Current * 0.001f;    //mV*mA
}
*/